import { MODEL_NAME } from '../../constants/model-names';
import { EVENTS, type IEventBus } from '../../events';
import type { BaseSnapshot } from '../../systems/save';
import { BaseModel } from '../base';

export const CURRENCY_TYPE = {
  SPIRIT_STONE: 'SPIRIT_STONE',
} as const;

export type CurrencyType = (typeof CURRENCY_TYPE)[keyof typeof CURRENCY_TYPE];

export const CURRENCY_TYPE_MAP = {
  [CURRENCY_TYPE.SPIRIT_STONE]: '灵石',
};

// 货币余额映射
export type CurrencyBalance = {
  [key in CurrencyType]: number;
};

export interface WalletV1 extends BaseSnapshot {
  version: 1;
  balances: CurrencyBalance;
}

export type WalletSnapshot = WalletV1;

export type WalletSnapshotOld = WalletV1;

export class WalletModel extends BaseModel {
  public name = MODEL_NAME.WALLET;
  protected bus: IEventBus;
  private balances: CurrencyBalance;

  constructor(bus: IEventBus) {
    super();
    this.bus = bus;

    // 初始化余额
    this.balances = {
      [CURRENCY_TYPE.SPIRIT_STONE]: 0,
    };
  }

  /**
   * 获取指定货币的余额
   */
  public getBalance(currency: CurrencyType): number {
    return this.balances[currency];
  }

  /**
   * 获取所有货币余额
   */
  public getAllBalances(): CurrencyBalance {
    return { ...this.balances };
  }

  /**
   * 增加货币
   */
  public addCurrency(currency: CurrencyType, amount: number) {
    if (amount <= 0) {
      return false;
    }

    const oldBalance = this.balances[currency];
    const newBalance = oldBalance + amount;

    this.balances[currency] = newBalance;

    this.bus.emit(EVENTS.WALLET_STATE_UPDATE);
  }

  /**
   * 消费货币
   */
  public spendCurrency(currency: CurrencyType, amount: number) {
    if (amount <= 0) {
      console.warn('消费的货币数量必须大于 0');
      return false;
    }

    const oldBalance = this.balances[currency];
    const newBalance = oldBalance - amount;

    // 检查余额是否足够
    if (newBalance < 0) {
      console.warn(`货币 ${currency} 余额不足`);
      return;
    }

    this.balances[currency] = newBalance;

    this.bus.emit(EVENTS.WALLET_STATE_UPDATE);
  }

  get uiState() {
    return {
      balances: this.balances,
    };
  }

  public save(): WalletSnapshot {
    return {
      version: 1,
      balances: this.balances,
    };
  }

  public load(snapshot: WalletSnapshot) {
    this.balances = snapshot.balances;
  }
}
